﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ForrajeriaDB; //ESTE USING VA EN TODOS LOS ELEMENTOS DE ESTA CAPA
using System.Data;
using System.Data.SqlClient;
namespace ForrajeriaDAL
{
    public class ForrajeDAL : AccesoDAL, InterfazDAL<ForrajeMO>
    {

        #region VARIABLES PARA STORED QUE MANEJA EL OBJETO DE DAL
        
        private static string insert = "Forraje_INSERT";
        private static string delete = "Forraje_DELETE";
        private static string update = "Forraje_UPDATE";
        private static string all = "Forraje_GetALL";
        private static string detalle = "AnimalXForraje_getbyForraje";
        private static string forrajexId = "Forraje_getByID";
        #endregion

         private SqlCommand cmd; //var de comando sql

        #region "Singleton"

        private static ForrajeDAL instance;

        private ForrajeDAL()
            : base()
        {
            
        }


        public static ForrajeDAL Instance
        {
            get
            {
                if (instance == null)
                {
                    instance = new ForrajeDAL();
                }
                return instance;
            }
        }

        #endregion

        #region Interfaz

        public List<ForrajeMO> GetAll()
        {
            SqlDataReader reader = null;
            List<ForrajeMO> lista = new List<ForrajeMO>();
            try
            {

                cmd = new SqlCommand(all, getConexion());
                cmd.CommandType = CommandType.StoredProcedure;
                opencon(); // abre coneccion 
                reader = cmd.ExecuteReader();
                while (reader.Read())
                {
                    
                    ForrajeMO aux = new ForrajeMO();
                  
//**************************************Formacion del objeto aux ******************************************************************
                    aux.CodigoEdad = int.Parse(reader["codigoEdad"].ToString());
                    aux.CodigoForraje = int.Parse(reader["codigoForraje"].ToString());
                    if (reader["descripcion"].ToString() != null)
                        aux.Descripcion = reader["descripcion"].ToString();
                    else
                        aux.Descripcion = "";

                    aux.NombreForraje = reader["nombreForraje"].ToString();
                    aux.StockActual = double.Parse(reader["stockActual"].ToString());
                    
                    if(reader["stockMinimo"].ToString() =="")
                    aux.StockMinimo = 0;
                    else
                        aux.StockMinimo = double.Parse(reader["stockMinimo"].ToString()); 
                    if(reader["stockMaximo"].ToString() =="")
                        aux.StockMaximo= null;
                    else
                        aux.StockMaximo= double.Parse(reader["stockMaximo"].ToString());
                    
                    if(reader["peso"].ToString() == "")
                        aux.Peso= null;
                    else
                        aux.Peso = double.Parse(reader["peso"].ToString());

                    aux.CodigoMarca = int.Parse(reader["CodigoMarca"].ToString());
                 
                    if (reader["estado"].ToString() != null)
                        aux.Estado = reader["estado"].ToString();
                    else
                        aux.Estado = "";
                    if (reader["precioXKilo"].ToString() != "")
                        aux.PrecioXKilo = double.Parse(reader["precioXKilo"].ToString());
                    else
                        aux.PrecioXKilo = 0;

//********************************** fin Formacion objeto aux **********************************************************************

                    lista.Add(aux);
                    aux = null;
                }
                return lista;
            }
            catch (Exception ex)
            {
                throw ex; //en caso que no pueda leer desde la base de datos tira el hacia la siguiente capa 
            }
           finally //finalmente cierro el reader que use para traer la consulta esto es importante ya que por alguna razon podria quedar abierto generando una conexion sin uso en la bd que estaria todo el tiempo abierta
            {
                closeReader(reader); //cierro el reader
                closecon();// cierra conexion

            }
        }

        public void Adicionar(ForrajeMO item)
        {
            item.CodigoForraje = getCodigoInsert("Forraje", "CodigoForraje"); //obtengo el codigo de insercion
            
            try
            {
                cmd = new SqlCommand(insert, getConexion());
                cmd.CommandType = CommandType.StoredProcedure;


                cmd.Parameters.Add("@codigoForraje", SqlDbType.Int).Value = item.CodigoForraje;
                cmd.Parameters.Add("@descripcion", SqlDbType.VarChar).Value = item.Descripcion;
                cmd.Parameters.Add("@nombreForraje", SqlDbType.VarChar).Value = item.NombreForraje;

                cmd.Parameters.Add("@stockActual", SqlDbType.Decimal).Value = item.StockActual;
                cmd.Parameters.Add("@stockMinimo", SqlDbType.Decimal).Value = item.StockMinimo;
                
                
                cmd.Parameters.Add("@stockMaximo", SqlDbType.Decimal).Value = item.StockMaximo;
                cmd.Parameters.Add("@codigoEdad", SqlDbType.Int).Value = item.CodigoEdad;
                cmd.Parameters.Add("@peso", SqlDbType.Decimal).Value = item.Peso;
                cmd.Parameters.Add("@estado", SqlDbType.VarChar).Value = item.Estado;
                cmd.Parameters.Add("@codigoMarca", SqlDbType.Int).Value = item.CodigoMarca;
                cmd.Parameters.Add("@precioXKilo", SqlDbType.Decimal).Value = item.PrecioXKilo;


                opencon(); //abro conexion
                cmd.ExecuteNonQuery();
                closecon(); //cierra conexion

            }
            catch (SqlException ex)
            {
                closecon();
                throw ex;
            }

        }

        public void Eliminar(ForrajeMO item)
        {
            try
            {
                cmd = new SqlCommand(delete, getConexion());
                cmd.CommandType = CommandType.StoredProcedure;
                cmd.Parameters.Add("@codigoForraje", SqlDbType.Int).Value = item.CodigoForraje;
                
                opencon();
                cmd.ExecuteNonQuery();
                closecon();
            }

            catch (SqlException ex)
            {
                closecon();
                throw ex;

            }
        }
        
        public void Actualizar(ForrajeMO nuevoItem, ForrajeMO origItem)
        {
            try
            {
                cmd = new SqlCommand(update, getConexion());
                cmd.CommandType = CommandType.StoredProcedure;



                cmd.Parameters.Add("@codigoForraje", SqlDbType.Int).Value = origItem.CodigoForraje;
                cmd.Parameters.Add("@descripcion", SqlDbType.VarChar).Value = nuevoItem.Descripcion;
                cmd.Parameters.Add("@nombreForraje", SqlDbType.VarChar).Value = nuevoItem.NombreForraje;

                cmd.Parameters.Add("@stockActual", SqlDbType.Decimal).Value = nuevoItem.StockActual;
                cmd.Parameters.Add("@stockMinimo", SqlDbType.Decimal).Value = nuevoItem.StockMinimo;


                cmd.Parameters.Add("@stockMaximo", SqlDbType.Decimal).Value = nuevoItem.StockMaximo;
                cmd.Parameters.Add("@codigoEdad", SqlDbType.Int).Value = nuevoItem.CodigoEdad;
                cmd.Parameters.Add("@peso", SqlDbType.Decimal).Value = nuevoItem.Peso;
                cmd.Parameters.Add("@estado", SqlDbType.VarChar).Value = nuevoItem.Estado;
                cmd.Parameters.Add("@codigoMarca", SqlDbType.Int).Value = nuevoItem.CodigoMarca;
                cmd.Parameters.Add("@precioXKilo", SqlDbType.Decimal).Value = nuevoItem.PrecioXKilo;

                opencon();
                cmd.ExecuteNonQuery();
                closecon();

            }
            catch (SqlException ex)
            {
                closecon();
                throw ex;
            }
        }

        #endregion
        public DataTable buscarProductos(string nombre, int edad, int marca)
        {
            DataTable dt = new DataTable();

            SqlDataAdapter da = null;


            try
            {
                cmd = new SqlCommand("Producto_Buscar", getConexion());

                cmd.CommandType = CommandType.StoredProcedure;
                cmd.Parameters.Add("@nombre", SqlDbType.VarChar).Value = nombre;
                cmd.Parameters.Add("@marca", SqlDbType.Int).Value = marca;
                cmd.Parameters.Add("@edad", SqlDbType.Int).Value = edad;

                opencon();
                da = new SqlDataAdapter(cmd);
                

                da.Fill(dt);

            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                closecon();

            }

            return dt;



        }
        public ForrajeMO getbyID(int codigo)
        {
            cmd =new SqlCommand(forrajexId, getConexion());
            cmd.CommandType = CommandType.StoredProcedure;

            cmd.Parameters.Add("@id",SqlDbType.Int).Value = codigo;
            SqlDataReader reader = null;
            try
            {
                opencon();
                reader = cmd.ExecuteReader();
                ForrajeMO aux = new ForrajeMO();
                if (reader.Read())
                {

                    aux.CodigoEdad = int.Parse(reader["codigoEdad"].ToString());
                    aux.CodigoForraje = int.Parse(reader["codigoForraje"].ToString());
                    if (reader["descripcion"].ToString() != null)
                        aux.Descripcion = reader["descripcion"].ToString();
                    else
                        aux.Descripcion = "";

                    aux.NombreForraje = reader["nombreForraje"].ToString();
                    aux.StockActual = double.Parse(reader["stockActual"].ToString());

                    if (reader["stockMinimo"].ToString() == "")
                        aux.StockMinimo = 0;
                    else
                        aux.StockMinimo = double.Parse(reader["stockMinimo"].ToString());
                    if (reader["stockMaximo"].ToString() == "")
                        aux.StockMaximo = null;
                    else
                        aux.StockMaximo = double.Parse(reader["stockMaximo"].ToString());

                    if (reader["peso"].ToString() == "")
                        aux.Peso = null;
                    else
                        aux.Peso = double.Parse(reader["peso"].ToString());

                    aux.CodigoMarca = int.Parse(reader["CodigoMarca"].ToString());

                    if (reader["estado"].ToString() != null)
                        aux.Estado = reader["estado"].ToString();
                    else
                        aux.Estado = "";
                    if (reader["precioXKilo"].ToString() != "")
                        aux.PrecioXKilo = double.Parse(reader["precioXKilo"].ToString());
                    else
                        aux.PrecioXKilo = 0;
                }
                reader.Close();
                closecon();
                return aux;

            }
            catch (Exception ex)
            {
                reader.Close();
                closecon();
                throw ex;
            }
        }

        public void modificarStock(int codigo, double stock)
        {
            try
            {
                SqlCommand cmd = new SqlCommand("Forraje_UPDATE_Stock", getConexion());
                cmd.CommandType = CommandType.StoredProcedure;

                cmd.Parameters.Add("@codigoForraje", SqlDbType.Int).Value = codigo;
                cmd.Parameters.Add("@stockActual", SqlDbType.Decimal).Value = stock;


                opencon();

                cmd.ExecuteNonQuery();

            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                closecon();
            }

        }


        public DataTable obtenerProductos()
        {
            DataTable dt = new DataTable();

            SqlDataAdapter da = null;


            try
            {
                cmd = new SqlCommand("Producto_GetAll", getConexion());

                cmd.CommandType = CommandType.StoredProcedure;

                opencon();
                da = new SqlDataAdapter(cmd);
                da.Fill(dt);

            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                closecon();

            }
           
            return dt;
            
           

        }
        public int AdicionarConTransaccion(ForrajeMO item)
        {
            item.CodigoForraje = getCodigoInsert("Forraje", "CodigoForraje"); //obtengo el codigo de insercion

            try
            {
               
                cmd = new SqlCommand(insert, getConexion());
                cmd.CommandType = CommandType.StoredProcedure;


                cmd.Parameters.Add("@codigoForraje", SqlDbType.Int).Value = item.CodigoForraje;
                cmd.Parameters.Add("@descripcion", SqlDbType.VarChar).Value = item.Descripcion;
                cmd.Parameters.Add("@nombreForraje", SqlDbType.VarChar).Value = item.NombreForraje;

                cmd.Parameters.Add("@stockActual", SqlDbType.Decimal).Value = item.StockActual;
                cmd.Parameters.Add("@stockMinimo", SqlDbType.Decimal).Value = item.StockMinimo;


                cmd.Parameters.Add("@stockMaximo", SqlDbType.Decimal).Value = item.StockMaximo;
                cmd.Parameters.Add("@codigoEdad", SqlDbType.Int).Value = item.CodigoEdad;
                cmd.Parameters.Add("@peso", SqlDbType.Decimal).Value = item.Peso;
                cmd.Parameters.Add("@estado", SqlDbType.VarChar).Value = item.Estado;
                cmd.Parameters.Add("@codigoMarca", SqlDbType.Int).Value = item.CodigoMarca;
                cmd.Parameters.Add("@precioXKilo", SqlDbType.Decimal).Value = item.PrecioXKilo;
                opencon(); //abro conexion
                cmd.ExecuteNonQuery();
                closecon(); 
               
                return item.CodigoForraje;
            }
            catch (SqlException ex)
            {

                closecon();
                throw ex;
            }
        }

        public void ActualizarConTransaccion(ForrajeMO nuevoItem, ForrajeMO origItem)
        {
             try
            {
                cmd = new SqlCommand(update, getConexion());
                cmd.CommandType = CommandType.StoredProcedure;



                cmd.Parameters.Add("@codigoForraje", SqlDbType.Int).Value = origItem.CodigoForraje;
                cmd.Parameters.Add("@descripcion", SqlDbType.VarChar).Value = nuevoItem.Descripcion;
                cmd.Parameters.Add("@nombreForraje", SqlDbType.VarChar).Value = nuevoItem.NombreForraje;

                cmd.Parameters.Add("@stockActual", SqlDbType.Decimal).Value = nuevoItem.StockActual;
                cmd.Parameters.Add("@stockMinimo", SqlDbType.Decimal).Value = nuevoItem.StockMinimo;


                cmd.Parameters.Add("@stockMaximo", SqlDbType.Decimal).Value = nuevoItem.StockMaximo;
                cmd.Parameters.Add("@codigoEdad", SqlDbType.Int).Value = nuevoItem.CodigoEdad;
                cmd.Parameters.Add("@peso", SqlDbType.Decimal).Value = nuevoItem.Peso;
                cmd.Parameters.Add("@estado", SqlDbType.VarChar).Value = nuevoItem.Estado;
                cmd.Parameters.Add("@codigoMarca", SqlDbType.Int).Value = nuevoItem.CodigoMarca;
                cmd.Parameters.Add("@precioXKilo", SqlDbType.Decimal).Value = nuevoItem.PrecioXKilo;

               opencon(); //abro conexion
                    cmd.ExecuteNonQuery();
                    closecon(); //cierra conexion
               

            }
            catch (SqlException ex)
            {
                closecon();
                throw ex;
            }
        }

        public List<AnimalMO> getDetalle(int id)
        {
            List<AnimalMO> lista = new List<AnimalMO>();
            SqlDataReader reader = null;
            try
            {
                cmd = new SqlCommand(detalle, getConexion());
                cmd.CommandType = CommandType.StoredProcedure;

                cmd.Parameters.Add("@id_forraje", SqlDbType.Int).Value = id;
                opencon();
          
                reader = cmd.ExecuteReader();
                while (reader.Read())
                {

                    AnimalMO aux = new AnimalMO();

                    //**************************************Formacion del objeto aux ******************************************************************
                    aux.CodigoAnimal = int.Parse(reader["Codigo"].ToString());
                    aux.Nombre = reader["Nombre"].ToString();
                    //********************************** fin Formacion objeto aux **********************************************************************

                    lista.Add(aux);
                    aux = null;
                }
                return lista;
             }
            catch (Exception ex)
            {
                throw ex; //en caso que no pueda leer desde la base de datos tira el hacia la siguiente capa 
            }
           finally //finalmente cierro el reader que use para traer la consulta esto es importante ya que por alguna razon podria quedar abierto generando una conexion sin uso en la bd que estaria todo el tiempo abierta
            {
                closeReader(reader); //cierro el reader
                closecon();// cierra conexion

            }
          

        }

        public DataTable reporteForrajeStock(string forraje = "", double stock = 0, bool minimo = false, string ordena = "", string dire="")
        {
            string sql = "";
            sql = "SELECT f.codigoForraje as 'Codigo_Forraje',f.nombreForraje as 'Nombre_Forraje',f.descripcion as 'Descripcion',f.stockMinimo as 'Stock_Minimo',f.stockActual as 'Stock_Actual',f.stockMaximo as 'Stock_Maximo',f.precioXKilo as 'Precio/Kilo', m.nombre as 'Marca', e.descripcion as 'Edad' "
                + " FROM Forraje f left join Marca m ON f.codigoMarca = m.codigoMarca left join Edades e on f.codigoEdad = e.codigoEdad WHERE f.estado = 'A' ";

            try
            {
                DataTable dt = new DataTable();

                SqlCommand cmd = new SqlCommand();

                if (forraje != "")
                {

                    sql += " and  f.nombreForraje like @forra+'%'";
                    cmd.Parameters.Add("@forra", SqlDbType.VarChar).Value = forraje;
                }

                if (minimo == false)
                {
                    if (stock != 0)
                    {
                        sql += " and  f.stockActual = @stock";
                        cmd.Parameters.Add("@stock", SqlDbType.Decimal).Value = stock;
                    }
                }
                else
                {
                    sql += " and f.stockActual <= f.stockMinimo";
                }
                if (ordena != "")
                {

                    sql += " Order by " + ordena;

                }
                if (dire != "")
                    sql += " " + dire;


                cmd.Connection = (getConexion());

                cmd.CommandText = sql;
                cmd.CommandType = CommandType.Text;
                SqlDataAdapter da = new SqlDataAdapter(cmd);

                opencon();
                da.Fill(dt);
                closecon();
                return dt;
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                closecon();
            }
        }

    }

}
